"""
列表命令实现

实现list相关命令的功能。
"""

import click
import json
from pathlib import Path
from typing import List, Dict, Any, Optional
from datetime import datetime

from .base import BaseCommand
from ...core.metadata import MetadataManager


class ListCommand(BaseCommand):
    """列表命令实现"""
    
    def __init__(self, config):
        """初始化列表命令"""
        super().__init__(config)
        # 使用配置中的备份目录作为元数据根目录
        backup_dir = getattr(config, 'backup_dir', './backups')
        self.metadata_manager = MetadataManager(backup_dir)
    
    def list_backups(self, status: Optional[str] = None, limit: int = 20) -> List[Dict[str, Any]]:
        """列出备份

        Args:
            status: 状态过滤
            limit: 限制数量

        Returns:
            备份列表
        """
        try:
            # 首先尝试从元数据管理器获取
            backups = self.metadata_manager.list_backups(status=status)

            # 如果没有找到，直接扫描备份目录
            if not backups:
                backups = self._scan_backup_directory()

            # 应用状态过滤
            if status:
                backups = [b for b in backups if b.get('status') == status]

            return backups[:limit] if limit > 0 else backups
        except Exception as e:
            self.logger.error(f"列出备份失败: {e}")
            return []
    
    def print_backups_table(self, backups: List[Dict[str, Any]]):
        """打印备份表格"""
        if not backups:
            click.echo("没有找到备份")
            return
        
        headers = ["备份ID", "源索引", "状态", "创建时间", "文档数", "大小"]
        rows = []
        
        for backup in backups:
            backup_id = backup.get('backup_id', '')[:20] + '...' if len(backup.get('backup_id', '')) > 20 else backup.get('backup_id', '')
            source_index = backup.get('source_index', '未知')
            status = backup.get('status', '未知')
            created_time = backup.get('created_time', '未知')[:19] if backup.get('created_time') else '未知'
            doc_count = f"{backup.get('document_count', 0):,}"
            size = self.format_size(backup.get('size_bytes', 0))
            
            rows.append([backup_id, source_index, status, created_time, doc_count, size])
        
        self.print_table(headers, rows, "备份列表")
    
    def print_backups_json(self, backups: List[Dict[str, Any]]):
        """打印备份JSON格式"""
        self.print_json(backups)
    
    def print_backups_yaml(self, backups: List[Dict[str, Any]]):
        """打印备份YAML格式"""
        self.print_yaml(backups)

    def _scan_backup_directory(self) -> List[Dict[str, Any]]:
        """扫描备份目录获取备份列表

        Returns:
            备份列表
        """
        backups = []
        backup_dir = getattr(self.config, 'backup_dir', './backups')
        backup_path = Path(backup_dir)

        if not backup_path.exists():
            return backups

        try:
            # 扫描备份目录中的所有子目录
            for item in backup_path.iterdir():
                if item.is_dir():
                    metadata_file = item / "metadata.json"
                    if metadata_file.exists():
                        try:
                            with open(metadata_file, 'r', encoding='utf-8') as f:
                                metadata = json.load(f)

                            # 智能检测实际状态
                            actual_status = self._detect_actual_status(metadata, item)

                            # 转换为标准格式
                            backup_info = {
                                'backup_id': metadata.get('backup_id', item.name),
                                'source_index': metadata.get('source_index', '未知'),
                                'status': actual_status,
                                'created_time': metadata.get('start_time', '未知'),
                                'document_count': metadata.get('total_documents', 0),
                                'size_bytes': self._calculate_backup_size(item),
                                'backup_path': str(item),
                                'strategy_type': metadata.get('strategy', {}).get('strategy_type', '未知') if isinstance(metadata.get('strategy'), dict) else '未知'
                            }
                            backups.append(backup_info)

                        except Exception as e:
                            self.logger.warning(f"读取备份元数据失败: {metadata_file}, {e}")
                            # 即使元数据读取失败，也添加基本信息
                            backup_info = {
                                'backup_id': item.name,
                                'source_index': '未知',
                                'status': '未知',
                                'created_time': datetime.fromtimestamp(item.stat().st_mtime).isoformat(),
                                'document_count': 0,
                                'size_bytes': self._calculate_backup_size(item),
                                'backup_path': str(item),
                                'strategy_type': '未知'
                            }
                            backups.append(backup_info)

            # 按创建时间排序
            backups.sort(key=lambda x: x.get('created_time', ''), reverse=True)

        except Exception as e:
            self.logger.error(f"扫描备份目录失败: {e}")

        return backups

    def _calculate_backup_size(self, backup_dir: Path) -> int:
        """计算备份目录的总大小

        Args:
            backup_dir: 备份目录路径

        Returns:
            总大小（字节）
        """
        total_size = 0
        try:
            for file_path in backup_dir.rglob('*'):
                if file_path.is_file():
                    total_size += file_path.stat().st_size
        except Exception as e:
            self.logger.warning(f"计算备份大小失败: {e}")

        return total_size

    def _detect_actual_status(self, metadata: Dict[str, Any], backup_dir: Path) -> str:
        """智能检测备份的实际状态

        Args:
            metadata: 元数据字典
            backup_dir: 备份目录路径

        Returns:
            实际状态
        """
        try:
            current_status = metadata.get('status', 'unknown')

            # 如果状态已经是 completed, failed, cancelled，直接返回
            if current_status in ['completed', 'failed', 'cancelled']:
                return current_status

            # 如果状态是 running，检查是否实际完成
            if current_status == 'running':
                # 检查是否有数据文件
                chunk_files = list(backup_dir.glob('chunk_*.json.gz'))
                if not chunk_files:
                    return 'failed'  # 没有数据文件，可能失败了

                # 检查是否有索引元数据
                index_metadata_file = backup_dir / 'index_metadata.json'
                if not index_metadata_file.exists():
                    return 'running'  # 还在进行中

                # 检查文档数量是否匹配
                total_docs = metadata.get('total_documents', 0)
                backed_up_docs = metadata.get('backed_up_documents', 0)

                # 如果有总文档数且备份文档数等于总文档数，认为已完成
                if total_docs > 0 and backed_up_docs >= total_docs:
                    return 'completed'

                # 如果有数据文件且有索引元数据，进一步检查
                # 检查数据文件的大小，如果有实际数据，很可能是完成的
                total_chunk_size = sum(f.stat().st_size for f in chunk_files)
                if total_chunk_size > 1024:  # 如果数据文件大于1KB，认为有实际数据
                    # 检查文件的修改时间，如果超过一定时间没有更新，可能已经完成
                    latest_file_time = max(
                        (f.stat().st_mtime for f in backup_dir.iterdir() if f.is_file()),
                        default=0
                    )

                    current_time = datetime.now().timestamp()
                    # 如果最后修改时间超过10分钟，且有数据文件，认为可能已经完成
                    if current_time - latest_file_time > 600:  # 10分钟
                        return 'completed'

                    # 如果文件很大（超过100KB），很可能已经完成
                    if total_chunk_size > 100 * 1024:  # 100KB
                        return 'completed'

                return 'running'

            return current_status

        except Exception as e:
            self.logger.warning(f"检测备份状态失败: {e}")
            return metadata.get('status', 'unknown')

    def execute(self, action: str, **kwargs) -> Any:
        """执行列表命令

        Args:
            action: 操作类型 ('list_backups')
            **kwargs: 其他参数

        Returns:
            执行结果
        """
        if action == 'list_backups':
            return self.list_backups(
                status=kwargs.get('status'),
                limit=kwargs.get('limit', 20)
            )
        else:
            raise ValueError(f"不支持的操作: {action}")
